package jmine.tec.script.persistent;

import java.util.Arrays;

import jmine.tec.script.persistent.domain.Script;
import jmine.tec.script.persistent.domain.ScriptDependency;
import jmine.tec.script.persistent.domain.ScriptLanguage;
import jmine.tec.script.persistent.domain.ScriptPurpose;
import jmine.tec.script.persistent.mock.MockLanguageIdentifier;
import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.services.testcase.DefaultRefDBTestCase;

/**
 * Classe abstrata dos testes unitários do módulo de scripts persistidos que utilizam base de dados.
 * 
 * @author lundberg
 */
public abstract class ScriptRefDBTestCase extends DefaultRefDBTestCase {

    /**
     * Construtor
     */
    public ScriptRefDBTestCase() {
        super();
    }

    /**
     * Construtor
     * 
     * @param name name
     */
    public ScriptRefDBTestCase(String name) {
        super(name);
    }

    /**
     * Cria o purpose e linguagens mock
     */
    protected void createMockPurposeAndLanguage() {
        this.createMockPurpose();
        this.createMockLanguage();
    }

    /**
     * Cria e retorna a linguagem mock
     * 
     * @return ScriptLanguage
     */
    @SuppressWarnings("deprecation")
    protected ScriptLanguage createMockLanguage() {
        BaseDAO<ScriptLanguage> dao = this.getController().getDAOFactory().getGenericDAO(ScriptLanguage.class);
        ScriptLanguage language = dao.createBean();
        language.setMnemonico(MockLanguageIdentifier.MOCK.name());
        language.setAbreviacao("MK");
        language.setExecutorClass("jmine.tec.script.persistent.mock.MockExecutor");
        this.getController().getSessionFactory().getCurrentSession().save(language, MockLanguageIdentifier.MOCK.getSystemId());
        return language;
    }

    /**
     * Cria e retorna a linguagem mock
     * 
     * @return ScriptLanguage
     */
    @SuppressWarnings("deprecation")
    protected ScriptLanguage createMooLanguage() {
        BaseDAO<ScriptLanguage> dao = this.getController().getDAOFactory().getGenericDAO(ScriptLanguage.class);
        ScriptLanguage language = dao.createBean();
        language.setMnemonico(MockLanguageIdentifier.MOO.name());
        language.setAbreviacao("MOO");
        language.setExecutorClass("jmine.tec.script.persistent.mock.MooExecutor");
        this.getController().getSessionFactory().getCurrentSession().save(language, MockLanguageIdentifier.MOO.getSystemId());
        return language;
    }

    /**
     * Cria e retorna o propósito mock
     * 
     * @return ScriptPurpose
     */
    protected ScriptPurpose createMockPurpose() {
        BaseDAO<ScriptPurpose> dao = this.getController().getDAOFactory().getGenericDAO(ScriptPurpose.class);
        ScriptPurpose purpose = dao.createBean();
        purpose.setMnemonico("MOCK_PURPOSE");
        purpose.setExecutionContext("jmine.tec.script.persistent.mock.MockScriptContextImpl");
        purpose.setDependencyContext("jmine.tec.script.persistent.mock.MockDependencyScriptContextImpl");
        purpose.setValidationContext("jmine.tec.script.persistent.mock.MockValidationScriptContextImpl");
        purpose.getPersister().save();
        return purpose;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getControllerSpringId() {
        return "scriptController";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String[] getResourcesBaseReferencia() {
        return new String[]{ "script-persistence-db.xml" };
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getSpringMainXMLFilename() {
        return "jmine-tec-script-persistence-test.xml";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected ScriptController getController() {
        return (ScriptController) super.getController();
    }

    /**
     * Cria o script com os parâmetros dados
     * 
     * @param id id
     * @param mnemonico mnemonico
     * @param descricao descricao
     * @param finalidade finalidade
     * @param imports imports
     * @param dependencies dependencies
     * @param body body
     * @return script
     */
    protected String createScript(Long id, String mnemonico, String descricao, String finalidade, String[] imports,
            String[][] dependencies, String body) {
        StringBuilder builder = new StringBuilder();
        if (id != null) {
            builder.append("Database ID: " + id);
            builder.append("\n");
        }
        if (mnemonico != null) {
            builder.append("Mnemônico: " + mnemonico);
            builder.append("\n");
        }
        if (descricao != null) {
            builder.append("Descrição: " + descricao);
            builder.append("\n");
        }
        if (finalidade != null) {
            builder.append("Finalidade: " + finalidade);
            builder.append("\n");
        }
        for (String imp : imports) {
            builder.append("Import: " + imp);
            builder.append("\n");
        }
        for (String[] dep : dependencies) {
            builder.append(String.format("Inject into: %s bean: %s\n", dep[0], dep[1]));
        }
        builder.append(body);
        String script = builder.toString();
        return script;
    }

    /**
     * Cria um script com os parâmetros dados, sem salvar.
     * 
     * @param mnemonico mnemonico
     * @param purp purpose
     * @param language language
     * @param body body
     * @return Script
     */
    protected Script createScript(String mnemonico, ScriptPurpose purp, ScriptLanguage language, String body) {
        return this.createScript(mnemonico, purp, language, body, new Script[0], new String[0][0]);
    }

    /**
     * Cria um script com os parâmetros dados, sem salvar.
     * 
     * @param mnemonico mnemonico
     * @param purp purpose
     * @param language language
     * @param body body
     * @param apis apis
     * @param dependencies dependencies
     * @return Script
     */
    protected Script createScript(String mnemonico, ScriptPurpose purp, ScriptLanguage language, String body, Script[] apis,
            String[][] dependencies) {
        BaseDAO<Script> dao = this.getController().getDAOFactory().getGenericDAO(Script.class);
        Script script = dao.createBean();
        script.setMnemonico(mnemonico);
        script.setPurpose(purp);
        script.setBody(body);
        script.setLanguage(language);
        script.getApis().addAll(Arrays.asList(apis));
        for (String[] dep : dependencies) {
            ScriptDependency dependency = new ScriptDependency();
            dependency.setVariable(dep[0]);
            dependency.setBean(dep[1]);
            script.getDependencies().add(dependency);
        }
        return script;
    }
}
